package scatter.generator.core;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.FileType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;
import scatter.common.pojo.po.BasePo;
import scatter.common.pojo.po.BaseTreePo;
import scatter.common.rest.controller.BaseAddUpdateQueryFormController;
import scatter.common.rest.controller.BaseInnerController;
import scatter.common.rest.service.*;
import scatter.common.rest.tools.StringTool;
import scatter.common.sqlinit.CustomDataSourceScriptDatabaseInitializer;
import scatter.generator.pojo.enums.CustomeTemplateType;
import scatter.generator.pojo.enums.TableType;
import scatter.generator.pojo.param.GenerateParam;
import scatter.generator.pojo.param.GenerateSeperateParam;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * <p>
 * 代码生成基类
 * </p>
 *
 * @author yangwei
 * @since 2020-10-27 22:42
 */
@Slf4j
public abstract class BaseGenerator {

    /**
     * location不可随意修改，请理解逻辑后修改
     */
    public static String SQL_LOCATION = "db";
    public static String SINGLE_SQL_TEMPLATE = "schema.{}.sql";
    /**
     * 静态字符串们，可以在模板中使用
     */
    public static enum StaticString{
        AddForm,
        UpdateForm,
        QueryForm,
        PageQueryForm,
        Vo,
        MapStruct,
        TransServiceImpl,
        mapstruct,
        Client,
        Configuration,
        Test,
        test,
        service,
        Service,
        controller,
        Controller,
        innerController,
        innercontroller,
        InnerController,
        serviceTest,
        ServiceTest,
        controllerTest,
        ControllerTest,
        innerControllerTest,
        InnerControllerTest,
        superTest,
        SuperTest,
        configuration,
        client,
        form,
        vo,

        Rel,
        rel,
        // 前端相关
        Add,
        SearchList,
        Update,
        Form,
        Mixin,
        Route,
        Table,
        Url,
    }



    protected CustomAutoGenerator mpg;

    public void setMpg(CustomAutoGenerator mpg) {
        this.mpg = mpg;
    }

    // 应该返回一个新的实例，以为避免数据配置不正确
    public CustomAutoGenerator getMpg() {
        return mpg;
    }

    /**
     * 实体和rest分开模块生成
     * @param param
     */
    public void doGenerateSeperate(GenerateSeperateParam param){

        log.info("**************************************生成开始{}",param.getTableName());

        GenerateParam generateParam = param;

        // po 配置
        List<CustomeTemplateType> poTemplates = new ArrayList<>();
        poTemplates.addAll(Arrays.asList(CustomeTemplateType.ENTITY,
                CustomeTemplateType.ADD_FORM,
                CustomeTemplateType.UPDATE_FORM,
                CustomeTemplateType.PAGE_QUERY_FORM,
                CustomeTemplateType.VO));
        if (param.getTableType() == TableType.rel) {
            poTemplates.addAll(Arrays.asList(CustomeTemplateType.ONE_ASSIGN_TWO_FORM, CustomeTemplateType.TWO_ASSIGN_ONE_FORM));
        }
        generateParam
                .setComponentPath(param.getPojoComponentPath())
                .setTemplates(
                        poTemplates.toArray(new CustomeTemplateType[0])
                );

        // 生成 po
        doGenerate(generateParam);

        // rest 配置
        generateParam
                .setComponentPath(param.getRestComponentPath())
                .setTemplates(
                        Arrays.asList(CustomeTemplateType.SERVICE,
                                CustomeTemplateType.MAPPER,
                                CustomeTemplateType.SCHEMA,
                                CustomeTemplateType.SERVICE_TEST,
                                CustomeTemplateType.CONTROLLER_TEST,
                                CustomeTemplateType.INNER_CONTROLLER_TEST,
                                CustomeTemplateType.SUPER_TEST,
                                CustomeTemplateType.INNER_CONTROLLER,
                                CustomeTemplateType.MAP_STRUCT,
                                CustomeTemplateType.CONTROLLER)
                                .toArray(new CustomeTemplateType[0])
                );
        // 生成 rest
        doGenerate(generateParam);

        // rest-client 配置
        generateParam
                .setComponentPath(param.getRestClientComponentPath())
                .setTemplates(
                        Arrays.asList(CustomeTemplateType.CLIENT)
                                .toArray(new CustomeTemplateType[0])
                );
        // 生成 rest-client
        doGenerate(generateParam);

        // rest-client-impl 配置
        generateParam
                .setComponentPath(param.getRestClientImplComponentPath())
                .setTemplates(
                        Arrays.asList(CustomeTemplateType.INNER_CONTROLLER)
                                .toArray(new CustomeTemplateType[0])
                );
        // 生成 rest-client-impl
        doGenerate(generateParam);

        // web配置
        generateParam
                .setComponentPath(param.getWebPath())
                .setTemplates(
                        Arrays.asList(CustomeTemplateType.ADD,
                                CustomeTemplateType.UPDATE,
                                CustomeTemplateType.SEARCH_LIST,
                                CustomeTemplateType.FORM,
                                CustomeTemplateType.MIXIN,
                                CustomeTemplateType.ROUTE,
                                CustomeTemplateType.TABLE,
                                CustomeTemplateType.URL,
                                CustomeTemplateType.ONE_ASSIGN_TWO_VUE,
                                CustomeTemplateType.TWO_ASSIGN_ONE_VUE
                                )
                                .toArray(new CustomeTemplateType[0])
                );
        // 生成web
        doGenerate(generateParam);
        log.info("**************************************生成完成{}",param.getTableName());
    }


    /**
     * 反选
     * @param disabledTemplates
     * @return
     */
    public CustomeTemplateType[] reverse(CustomeTemplateType[] disabledTemplates) {
        List<CustomeTemplateType> result = new ArrayList<>();
        for (CustomeTemplateType value : CustomeTemplateType.values()) {
            boolean exist = false;
            for (CustomeTemplateType disabledTemplate : disabledTemplates) {
                if (disabledTemplate == value) {
                    exist = true;
                    break;
                }
            }
            if (!exist) {
                result.add(value);
            }
        }
        return result.toArray(new CustomeTemplateType[0]);
    }

    /**
     * 代码生成
     * @param param
     */
    public void doGenerate(GenerateParam param) {

        // 代码生成器
        if (mpg == null) {
            mpg = getMpg();
            if (mpg == null) {
                mpg = new CustomAutoGenerator();
            }
        }

        mpg.setGlobalConfig(globalConfig(param.getAuthor(),param.getComponentPath(),param.isFileOverride()));

        mpg.setDataSource(dataSourceConfig());

        mpg.setPackageInfo(packageConfig(param.getModuleName(),param.getPackageParent(),param.getEntityPackageParent()));

        mpg.setStrategy(strategyConfig(param.getTableName(),param.getTableType(),param.getTablePrefix()));

        mpg.setTemplate(templateConfig(reverse(param.getTemplates())));

        mpg.setTemplateEngine(new FreemarkerTemplateEngine());

        InjectionConfig injectionConfig = injectionConfig(param.getTableType(),param.getComponentName(),param.getModuleName());

        mpg.setCfg(injectionConfig);
        injectionConfig.setFileOutConfigList(fileOutConfigs(param.getTableType(),param.getModuleName(),reverse(param.getTemplates())));

        if (param.isDeleteFile()) {
            injectionConfig.setFileCreate(iFileCreate(param.isDeleteFile()));
        }

        mpg.execute();

        // 处理schema
        DataSourceConfig dataSource = mpg.getDataSource();
        if (Arrays.stream(param.getTemplates()).filter(t->t == CustomeTemplateType.SCHEMA).findFirst().orElse(null) != null) {
            for (TableInfo tableInfo : mpg.getAllTableInfoList(mpg.getConfig())) {

                String schemaPath = schemaDirAbsolutePath() + "/" + StrUtil.format("{}-schema.sql", param.getComponentName());

                if (!FileUtil.exist(schemaPath)) {
                    FileUtil.touch(schemaPath);
                }
                String singleSqlName = StrUtil.format(SINGLE_SQL_TEMPLATE,tableInfo.getName());
                String content = FileUtil.readUtf8String(schemaPath);
                if(StrUtil.isEmpty(content) || !content.contains(singleSqlName)){
                    // importLocation如：-- import classpath:db/schema.component_area.sql
                    String importLocation = System.getProperty("line.separator") + CustomDataSourceScriptDatabaseInitializer.IMPORT_PREFIX + "classpath:"+ SQL_LOCATION+"/"+singleSqlName;
                    FileUtil.appendUtf8String(importLocation, schemaPath);
                }
            }
        }

        // mybatisplus并没有关闭数据源，这里手动尝试关闭
        if(dataSource instanceof CustomDataSourceConfig){
            ((CustomDataSourceConfig) dataSource).closeAllConnection();
        }
        mpg = null;
    }

    /**
     * 原始组件名称转换 主要用于db schema名称获取
     * @param componentName
     * @return
     */
    public abstract String componentNameConvertToNoLine(String componentName);
    public abstract String componentNameConvertToUnderLine(String componentName);

    /**
     * 全局配置
     * @param author
     * @param componentPath
     * @return
     */
    public GlobalConfig globalConfig(String author,String componentPath, boolean fileOverride) {
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + componentPath + "/src/main/java");
        gc.setAuthor(author);
        gc.setOpen(false);
        // 实体属性 Swagger2 注解
        gc.setSwagger2(true);
        gc.setFileOverride(fileOverride);
        return gc;
    }

    /**
     *
     * @return
     */
    public TemplateConfig templateConfig(CustomeTemplateType... disabledTemplateTypes) {
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setController("/templates/original/controller.java");
        templateConfig.setService("/templates/original/service.java");
        templateConfig.setServiceImpl("/templates/original/serviceImpl.java");
        templateConfig.setEntity("/templates/original/entity.java");
        // 不生成的模板
        if (disabledTemplateTypes != null) {
            for (CustomeTemplateType templateType : disabledTemplateTypes) {
                TemplateType templateType1 = null;
                try {
                    templateType1 = TemplateType.valueOf(templateType.name());
                } catch (IllegalArgumentException e) {
                    templateType1 = null;
                }
                if (templateType1 != null) {
                    templateConfig.disable(templateType1);
                }
            }
        }

        return templateConfig;
    }

    /**
     * 策略配置
     * @param tableName
     * @return
     */
    public StrategyConfig strategyConfig(String tableName,TableType tableType,String tablePrefix) {
        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setSuperEntityClass(BasePo.class);
        if (tableType == TableType.tree) {
            strategy.setSuperEntityClass(BaseTreePo.class);
        }
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        // 公共父类
        strategy.setSuperControllerClass(BaseAddUpdateQueryFormController.class);
        if (tableType == TableType.tree) {
            strategy.setSuperServiceImplClass(IBaseAddUpdateQueryFormServiceImpl.class);
            strategy.setSuperServiceClass(IBaseService.class);
        }else if (tableType == TableType.rel) {
            strategy.setSuperServiceImplClass(IBaseAddUpdateQueryFormServiceImpl.class);
            strategy.setSuperServiceClass(IBaseService.class);
        }else {
            strategy.setSuperServiceImplClass(IBaseAddUpdateQueryFormServiceImpl.class);
            strategy.setSuperServiceClass(IBaseService.class);
        }



        strategy.setSuperMapperClass(IBaseMapper.class.getName());

        strategy.setChainModel(true);

        List<String> tableNames = new ArrayList<>();
        for (String name : tableName.split(",")) {
            tableNames.add(name.trim());
        }

        if (StrUtil.isNotEmpty(tablePrefix)) {
            strategy.setTablePrefix(tablePrefix);
        }
        strategy.setInclude(String.join(",",tableNames));
        strategy.setControllerMappingHyphenStyle(true);
        return strategy;
    }

    /**
     * 包配置
     * @param moduleName
     * @return
     */
    public PackageConfig packageConfig(String moduleName,String parent,String entityParent) {
        // 包配置
        CustomPackageConfig pc = new CustomPackageConfig();

        pc.setEntity("po");

        pc.setModuleName(moduleName);
        if (StrUtil.isEmpty(entityParent)) {
            pc.setParent(parent);
        }else {
            String newModuleName = StrUtil.isEmpty(moduleName)? "" : (StringPool.DOT + moduleName);
            pc.setParent("");
            pc.setEntity(entityParent + newModuleName + StringPool.DOT + pc.getEntity());
            pc.setService(parent + newModuleName + StringPool.DOT + pc.getService());
            pc.setServiceImpl(parent + newModuleName + StringPool.DOT + pc.getServiceImpl());
            pc.setMapper(parent + newModuleName + StringPool.DOT + pc.getMapper());
            pc.setXml(parent + newModuleName + StringPool.DOT + pc.getXml());
            pc.setController(parent + newModuleName + StringPool.DOT + pc.getController());
        }

        return pc;
    }

    /**
     * 数据库配置
     * @return
     */
    public CustomDataSourceConfig dataSourceConfig(){
        return null;
    }

    /**
     * rel分配文件名部分
     * @param tableInfo
     * @param relTableComment1
     * @param relTableComment2
     * @return
     */
    public String getOneAssignTwoName(TableInfo tableInfo, String relTableComment1, String relTableComment2) {
        String r = null;
        String prop1 = StrUtil.removeSuffix(getTableFieldByComment(tableInfo,relTableComment1).getPropertyName(),"Id");
        String prop2 = StrUtil.removeSuffix(getTableFieldByComment(tableInfo,relTableComment2).getPropertyName(),"Id");
        if(prop1 != null && prop2 != null){
            r = StrUtil.upperFirst(prop1)+ "Assign" + StrUtil.upperFirst(prop2);
        }
        return r;
    }

    public TableField getTableFieldByComment(TableInfo tableInfo,String comment) {
        for (TableField field : tableInfo.getFields()) {
            if (field.getComment().contains(comment)) {
                return field;
            }
        }
        return null;
    }
    /**
     * 自定义注入属性
     * @return
     */
    public InjectionConfig injectionConfig(TableType tableType,String componentName,String moduleName) {

        DataSourceConfig dataSourceConfig = mpg.getDataSource();
        Connection connection = dataSourceConfig.getConn();
        DbType dbType = dataSourceConfig.getDbType();
        IDbQuery dbQuery = dataSourceConfig.getDbQuery();
        return new CustomInjectionConfig() {

            @Override
            public InjectionConfig setMap(Map<String, Object> map) {
                if (getMap() == null) {
                    return super.setMap(map);
                }else{
                    getMap().putAll(map);
                    return this;
                }
            }

            @Override
            public void initMap() {
                Map<String,Object> map = new HashMap<>();
                // to do nothing
                Map<String, Object> staticStringMap = new HashMap<>();
                for (StaticString value : StaticString.values()) {
                    staticStringMap.put(value.name(), value.name());
                }
                map.put("staticString", staticStringMap);

                map.put("entityParentPkg", entityParentPkg());
                map.put("formPkg", formPkg());
                map.put("voPkg", voPkg());
                map.put("mapStructPkg", mapStructPkg());
                map.put("clientPkg", clientPkg());
                map.put("configurationPkg", configurationPkg());

                map.put("testPkg", testPkg(moduleName));
                map.put("testServicePkg", testServicePkg(moduleName));
                map.put("testControllerPkg", testControllerPkg(moduleName));
                map.put("testInnerControllerPkg", testInnerControllerPkg(moduleName));


                map.put("tableType", tableType.name());

                if (tableType == TableType.tree) {
                    map.put("innerControllerSuperClass", BaseInnerController.class.getName());
                    map.put("innerControllerSuperClassName", BaseInnerController.class.getSimpleName());
                }else if (tableType == TableType.rel) {
                    map.put("innerControllerSuperClass", BaseInnerController.class.getName());
                    map.put("innerControllerSuperClassName", BaseInnerController.class.getSimpleName());
                }else {
                    map.put("innerControllerSuperClass", BaseInnerController.class.getName());
                    map.put("innerControllerSuperClassName", BaseInnerController.class.getSimpleName());
                }

                setMap(map);
            }

            @Override
            public void initTableMap(TableInfo tableInfo) {
                Map<String, Object> map = new HashMap<>();
                String tableComment = tableInfo instanceof CustomTableInfo ? ((CustomTableInfo) tableInfo).getCommentSimple() : tableInfo.getComment();
                map.put("tableComment", tableComment);
                if (tableType == TableType.rel && tableInfo instanceof CustomTableInfo) {

                    String tableCommentRelOne = ((CustomTableInfo) tableInfo).getCommentRel1();
                    String tableCommentRelTwo = ((CustomTableInfo) tableInfo).getCommentRel2();
                    map.put("relTableComment1", tableCommentRelOne);
                    map.put("relTableComment2", tableCommentRelTwo);


                    String relOnePropertyName = getTableFieldByComment(tableInfo,tableCommentRelOne).getPropertyName();
                    map.put("relOnePropertyName", relOnePropertyName);
                    map.put("relOnePropertyNameSimple", StrUtil.removeSuffix(relOnePropertyName,"Id"));
                    String relTwoPropertyName = getTableFieldByComment(tableInfo,tableCommentRelTwo).getPropertyName();
                    map.put("relTwoPropertyName", relTwoPropertyName);
                    map.put("relTwoPropertyNameSimple", StrUtil.removeSuffix(relTwoPropertyName,"Id"));

                    map.put("oneAssignTwoForm", StrUtil.upperFirst(getOneAssignTwoName(tableInfo,tableCommentRelOne,tableCommentRelTwo)  + StaticString.Form));
                    map.put("twoAssignOneForm", StrUtil.upperFirst(getOneAssignTwoName(tableInfo,tableCommentRelTwo,tableCommentRelOne) + StaticString.Form));

                }



                map.put("addForm",tableInfo.getEntityName()+ StaticString.AddForm);
                map.put("updateForm",tableInfo.getEntityName()+ StaticString.UpdateForm);
                map.put("pageQueryForm",tableInfo.getEntityName()+ StaticString.PageQueryForm);
                map.put("vo",tableInfo.getEntityName()+ StaticString.Vo);
                map.put("mapStruct",tableInfo.getEntityName()+ StaticString.MapStruct);
                map.put("client",tableInfo.getEntityName()+ StaticString.Client);
                map.put("innerController",tableInfo.getEntityName()+ StaticString.InnerController);
                map.put("configuration",StrUtil.upperFirst(StringTool.lineToHump(componentNameConvertToUnderLine(componentName))) + StaticString.Configuration);

                map.put("serviceTest",tableInfo.getEntityName()+ StaticString.ServiceTest);
                map.put("controllerTest",tableInfo.getEntityName()+ StaticString.ControllerTest);
                map.put("innerControllerTest",tableInfo.getEntityName()+ StaticString.InnerControllerTest);
                map.put("superTest",tableInfo.getEntityName()+ StaticString.SuperTest);

                map.put("createTableSql", createTableSql(connection, tableInfo.getName()));
                setMap(map);
            }
        };
    }

    /**
     * 获取建表语句
     * @param connection
     * @param tableName
     * @return
     */
    public String createTableSql(Connection connection, String tableName) {
        try (
                Connection conn = connection;
                PreparedStatement preparedStatement = conn.prepareStatement("show create table " + tableName);
                ResultSet results = preparedStatement.executeQuery()) {
            while (results.next()) {
                String createTableSql = results.getString("Create Table");
                return "DROP TABLE IF EXISTS "+ tableName +";"
                        + System.getProperty("line.separator")
                        + createTableSql + ";"
                        + System.getProperty("line.separator");
            }
        } catch (SQLException e) {
            System.err.println("SQL Exception：" + e.getMessage());
        }
        return "";
    }
    /**
     * form 表单包
     * @return
     */
    public String serviceImplPkg() {
        return mpg.getPackageInfo().getServiceImpl();
    }
    /**
     * mspStruct 包
     * @return
     */
    public String clientPkg() {
        return controllerParentPkg() + StringPool.DOT + StaticString.client.name();
    }

    /**
     * mspStruct 包
     * @return
     */
    public String mapStructPkg() {
        return controllerParentPkg() + StringPool.DOT + StaticString.mapstruct.name();
    }

    /**
     * vo 包
     * @return
     */
    public String voPkg() {
        return entityParentPkg() + StringPool.DOT + StaticString.vo.name();
    }

    /**
     * form 表单包
     * @return
     */
    public String formPkg() {
        return entityParentPkg() + StringPool.DOT + StaticString.form.name();
    }

    /**
     * controller的父级包
     * @return
     */
    public String controllerParentPkg() {
        return mpg.getPackageInfo().getController().substring(0, mpg.getPackageInfo().getController().lastIndexOf(StringPool.DOT));
    }

    /**
     * 实体的父级包
     * @return
     */
    public String entityParentPkg() {
        return mpg.getPackageInfo().getEntity().substring(0, mpg.getPackageInfo().getEntity().lastIndexOf(StringPool.DOT));
    }
    /**
     * 配置包
     * @return
     */
    public String configurationPkg() {
        String controllerPkg =  controllerParentPkg();
        if (StringUtils.isNotBlank(mpg.getPackageInfo().getModuleName())) {
            controllerPkg = controllerPkg.replace(StringPool.DOT + mpg.getPackageInfo().getModuleName(), "");
        }
        return controllerPkg;
    }

    /**
     * 测试包路径
     * @return
     */
    public String testPkg(String moduleName) {
        if (StrUtil.isEmpty(moduleName)) {
            return controllerParentPkg()+ StringPool.DOT + StaticString.test.name();
        }else {
            return controllerParentPkg().substring(0,controllerParentPkg().lastIndexOf(StringPool.DOT))+ StringPool.DOT + StaticString.test.name()+ StringPool.DOT + moduleName;
        }
    }

    /**
     * service 测试包
     * @param moduleName
     * @return
     */
    public String testServicePkg(String moduleName) {return testPkg(moduleName) + StringPool.DOT + StaticString.service;}

    /**
     * controller 测试包
     * @param moduleName
     * @return
     */
    public String testControllerPkg(String moduleName) {return testPkg(moduleName) + StringPool.DOT + StaticString.controller;}

    /**
     * innerController 测试包
     * @param moduleName
     * @return
     */
    public String testInnerControllerPkg(String moduleName) {return testPkg(moduleName) + StringPool.DOT + StaticString.innercontroller;}

    /**
     * 包路径转文件路径
     * @param pkg
     * @return
     */
    public String pkgToPath(String pkg) {
        return pkg.replace(".", "/");
    }

    /**
     * shcema的路径目录地址
     * @return
     */
    public String schemaDirAbsolutePath() {
        return mpg.getGlobalConfig().getOutputDir().replace("/main/java", "/main/resources/" + SQL_LOCATION);
    }

    /**
     * java文件测试目录
     * @return
     */
    public String testJavaDirAbsolutePath() {
        return mpg.getGlobalConfig().getOutputDir().replace("/main/java", "/test/java");
    }

    /**
     * 前端文本目录
     * @return
     */
    public String webDirAbsolutePath() {
        return mpg.getGlobalConfig().getOutputDir().replace("/src/main/java", "");
    }


    /**
     * 删除生成的文件
     * @param deleteFile
     * @return
     */
    public IFileCreate iFileCreate(boolean deleteFile) {
        return new IFileCreate(){

            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                if (deleteFile) {
                    boolean del = FileUtil.del(filePath);
                    if (del) {
                        log.info("文件已删除，path={}",filePath);
                    }else {
                        log.error("文件删除失败，path={}",filePath);
                    }
                }else {
                    checkDir(filePath);
                }
                return !deleteFile;
            }
        };
    }

    /**
     * 自定义文件
     * @param disabledTemplateTypes
     * @return
     */
    public List<FileOutConfig> fileOutConfigs(TableType tableType,String moduleName,CustomeTemplateType... disabledTemplateTypes) {
        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();

        Map<CustomeTemplateType, Boolean> disabledTemplateTypesMap = new HashMap<>();
        if (disabledTemplateTypes != null) {
            for (CustomeTemplateType disabledTemplateType : disabledTemplateTypes) {
                disabledTemplateTypesMap.put(disabledTemplateType, true);
            }
        }
        /**
         * 翻译服务
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.SERVICE) == null) {
            focList.add(new FileOutConfig("/templates/transServiceImpl.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return mpg.getGlobalConfig().getOutputDir()
                            + "/" + pkgToPath(serviceImplPkg())
                            + "/" + tableInfo.getEntityName() + StaticString.TransServiceImpl.name() + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * 添加表单
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.ADD_FORM) == null) {
            focList.add(new FileOutConfig("/templates/addForm.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return mpg.getGlobalConfig().getOutputDir()
                            + "/" + pkgToPath(formPkg())
                            + "/" + tableInfo.getEntityName() + StaticString.AddForm.name() + StringPool.DOT_JAVA;
                }
            });
        }

        /**
         * 修改表单
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.UPDATE_FORM) == null) {
            focList.add(new FileOutConfig("/templates/updateForm.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return mpg.getGlobalConfig().getOutputDir()
                            + "/" + pkgToPath(formPkg())
                            + "/" + tableInfo.getEntityName() + StaticString.UpdateForm.name() + StringPool.DOT_JAVA;
                }
            });
        }

        /**
         * 分页查询表单，当前分页查询和不分页查询共用一个
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.PAGE_QUERY_FORM) == null) {
            focList.add(new FileOutConfig("/templates/pageQueryForm.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return mpg.getGlobalConfig().getOutputDir()
                            + "/" + pkgToPath(formPkg())
                            + "/" + tableInfo.getEntityName() + StaticString.PageQueryForm.name() + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * rel数据分配表单
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.ONE_ASSIGN_TWO_FORM) == null  && tableType == TableType.rel) {
            focList.add(new FileOutConfig("/templates/relOneAssignTwoForm.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return mpg.getGlobalConfig().getOutputDir()
                            + "/" + pkgToPath(formPkg())
                            + "/" + mpg.getCfg().getMap().get("oneAssignTwoForm") + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * rel数据分配表单
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.TWO_ASSIGN_ONE_FORM) == null  && tableType == TableType.rel) {
            focList.add(new FileOutConfig("/templates/relTwoAssignOneForm.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return mpg.getGlobalConfig().getOutputDir()
                            + "/" + pkgToPath(formPkg())
                            + "/" + mpg.getCfg().getMap().get("twoAssignOneForm") + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * vo 数据响应
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.VO) == null) {
            focList.add(new FileOutConfig("/templates/vo.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return mpg.getGlobalConfig().getOutputDir()
                            + "/" + pkgToPath(voPkg())
                            + "/" + tableInfo.getEntityName() + StaticString.Vo.name() + StringPool.DOT_JAVA;
                }
            });
        }

        /**
         * mapStruct
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.MAP_STRUCT) == null) {
            focList.add(new FileOutConfig("/templates/mapStruct.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return mpg.getGlobalConfig().getOutputDir()
                            + "/" + pkgToPath(mapStructPkg())
                            + "/" + tableInfo.getEntityName() + StaticString.MapStruct.name() + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * inner controller
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.INNER_CONTROLLER) == null) {
            focList.add(new FileOutConfig("/templates/innerController.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return mpg.getGlobalConfig().getOutputDir()
                            + "/" + pkgToPath(mpg.getPackageInfo().getController())
                            + "/" + tableInfo.getEntityName() + StaticString.InnerController.name() + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * client
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.CLIENT) == null) {
            focList.add(new FileOutConfig("/templates/client.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return mpg.getGlobalConfig().getOutputDir()
                            + "/" + pkgToPath(clientPkg())
                            + "/" + tableInfo.getEntityName() + StaticString.Client.name() + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * 单表建表语句sql
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.SCHEMA) == null) {
            focList.add(new FileOutConfig("/templates/schema.sql.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return schemaDirAbsolutePath()
                            + "/"
                            + StrUtil.format(SINGLE_SQL_TEMPLATE,tableInfo.getName());
                }
            });
        }
        /**
         * service test
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.SERVICE_TEST) == null) {
            focList.add(new FileOutConfig("/templates/test/serviceTest.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return testJavaDirAbsolutePath()
                            + "/"
                            + pkgToPath(testServicePkg(moduleName))
                            + "/" + tableInfo.getEntityName() + StaticString.ServiceTest.name() + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * controller test
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.CONTROLLER_TEST) == null) {
            focList.add(new FileOutConfig("/templates/test/controllerTest.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return testJavaDirAbsolutePath()
                            + "/"
                            + pkgToPath(testControllerPkg(moduleName))
                            + "/" + tableInfo.getEntityName() + StaticString.ControllerTest.name() + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * inner controller test
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.INNER_CONTROLLER_TEST) == null) {
            focList.add(new FileOutConfig("/templates/test/innerControllerTest.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return testJavaDirAbsolutePath()
                            + "/"
                            + pkgToPath(testInnerControllerPkg(moduleName))
                            + "/" + tableInfo.getEntityName() + StaticString.InnerControllerTest.name() + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * super test
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.SUPER_TEST) == null) {
            focList.add(new FileOutConfig("/templates/test/superTest.java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return testJavaDirAbsolutePath()
                            + "/"
                            + pkgToPath(testPkg(moduleName))
                            + "/" + tableInfo.getEntityName() + StaticString.SuperTest.name() + StringPool.DOT_JAVA;
                }
            });
        }
        /**
         * 添加页面
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.ADD) == null) {
            focList.add(new FileOutConfig("/templates/web/element/Add.vue.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return  webDirAbsolutePath()
                            + (StrUtil.isNotEmpty(moduleName) ? "/" + pkgToPath(moduleName) : "")
                            + "/element"
                            + "/" + tableInfo.getEntityName() + StaticString.Add.name() + StringPool.DOT + "vue";
                }
            });
        }
        /**
         * 修改页面
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.UPDATE) == null) {
            focList.add(new FileOutConfig("/templates/web/element/Update.vue.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return  webDirAbsolutePath()
                            + (StrUtil.isNotEmpty(moduleName) ? "/" + pkgToPath(moduleName) : "")
                            + "/element"
                            + "/" + tableInfo.getEntityName() + StaticString.Update.name() + StringPool.DOT + "vue";
                }
            });
        }
        /**
         * 列表页面
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.SEARCH_LIST) == null) {
            focList.add(new FileOutConfig("/templates/web/element/SearchList.vue.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return  webDirAbsolutePath()
                            + (StrUtil.isNotEmpty(moduleName) ? "/" + pkgToPath(moduleName) : "")
                            + "/element"
                            + "/" + tableInfo.getEntityName() + StaticString.SearchList.name() + StringPool.DOT + "vue";
                }
            });
        }
        /**
         * 表单
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.FORM) == null) {
            focList.add(new FileOutConfig("/templates/web/Form.js.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return  webDirAbsolutePath()
                            + (StrUtil.isNotEmpty(moduleName) ? "/" + pkgToPath(moduleName) : "")
                            + "/" + tableInfo.getEntityName() + StaticString.Form.name() + StringPool.DOT + "js";
                }
            });
        }
        /**
         * 混入
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.MIXIN) == null) {
            focList.add(new FileOutConfig("/templates/web/Mixin.js.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return  webDirAbsolutePath()
                            + (StrUtil.isNotEmpty(moduleName) ? "/" + pkgToPath(moduleName) : "")
                            + "/" + tableInfo.getEntityName() + StaticString.Mixin.name() + StringPool.DOT + "js";
                }
            });
        }
        /**
         * 路由
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.ROUTE) == null) {
            focList.add(new FileOutConfig("/templates/web/Route.js.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return  webDirAbsolutePath()
                            + (StrUtil.isNotEmpty(moduleName) ? "/" + pkgToPath(moduleName) : "")
                            + "/" + tableInfo.getEntityName() + StaticString.Route.name() + StringPool.DOT + "js";
                }
            });
        }
        /**
         * 表格
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.TABLE) == null) {
            focList.add(new FileOutConfig("/templates/web/Table.js.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return  webDirAbsolutePath()
                            + (StrUtil.isNotEmpty(moduleName) ? "/" + pkgToPath(moduleName) : "")
                            + "/" + tableInfo.getEntityName() + StaticString.Table.name() + StringPool.DOT + "js";
                }
            });
        }
        /**
         * 请求地址url
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.URL) == null) {
            focList.add(new FileOutConfig("/templates/web/Url.js.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return  webDirAbsolutePath()
                            + (StrUtil.isNotEmpty(moduleName) ? "/" + pkgToPath(moduleName) : "")
                            + "/" + tableInfo.getEntityName() + StaticString.Url.name() + StringPool.DOT + "js";
                }
            });
        }
        /**
         * 关系表分配1
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.ONE_ASSIGN_TWO_VUE) == null && tableType == TableType.rel) {
            focList.add(new FileOutConfig("/templates/web/element/relOneAssignTwo.vue.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {


                    String tableCommentRelOne = ((CustomTableInfo) tableInfo).getCommentRel1();
                    String tableCommentRelTwo = ((CustomTableInfo) tableInfo).getCommentRel2();
                    return  webDirAbsolutePath()
                            + (StrUtil.isNotEmpty(moduleName) ? "/" + pkgToPath(moduleName) : "")
                            + "/element"

                            + "/" + getOneAssignTwoName(tableInfo,tableCommentRelOne,tableCommentRelTwo) + StaticString.Rel.name() + StringPool.DOT + "vue";
                }
            });
        }
        /**
         * 关系表分配2
         */
        if (disabledTemplateTypesMap.get(CustomeTemplateType.ONE_ASSIGN_TWO_VUE) == null && tableType == TableType.rel) {
            focList.add(new FileOutConfig("/templates/web/element/relTwoAssignOne.vue.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {


                    String tableCommentRelOne = ((CustomTableInfo) tableInfo).getCommentRel1();
                    String tableCommentRelTwo = ((CustomTableInfo) tableInfo).getCommentRel2();
                    return  webDirAbsolutePath()
                            + (StrUtil.isNotEmpty(moduleName) ? "/" + pkgToPath(moduleName) : "")
                            + "/element"

                            + "/" + getOneAssignTwoName(tableInfo,tableCommentRelTwo,tableCommentRelOne) + StaticString.Rel.name() + StringPool.DOT + "vue";
                }
            });
        }
        return focList;
    }
}
